package com.example.yingjiguanli_demo.aspect;

import com.example.yingjiguanli_demo.aspect.interfaces.RequirePermission;
import com.example.yingjiguanli_demo.config.SessionManager;
import com.example.yingjiguanli_demo.mapper.UserRoleMapper;
import com.example.yingjiguanli_demo.mapper.UsersMapper;
import com.example.yingjiguanli_demo.pojo.Users;
import com.example.yingjiguanli_demo.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.SQLSyntaxErrorException;
import java.util.List;

@Aspect
@Component
@Slf4j
public class PermissionAspect {

    @Autowired
    private SessionManager sessionManager;

    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private UsersMapper usersMapper;

    private static final String USER_SESSION_NAME = "SESSIONID";
    private static final int STATUS_DISABLED = 1;

    @Around("@annotation(requirePermission)")
    public Object checkPermission(ProceedingJoinPoint joinPoint, RequirePermission requirePermission) throws Throwable {
        // 获取Request和Response
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        HttpServletResponse response = attributes.getResponse();
        String uri = request.getRequestURI();
        log.info("访问 URI => {}", uri);

        // 从Cookies中获取SESSIONID
        String sessionId = getSessionIdFromCookies(request.getCookies());
        if (sessionId == null) {
            log.warn("未找到SESSIONID Cookie");
            assert response != null;
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return null;
        }

        // 获取并验证Token
        String token = sessionManager.getSession(sessionId);
        if (token == null) {
            log.warn("无效的Session ID: {}。未经授权的访问尝试: {}", sessionId, uri);
            assert response != null;
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return null;
        }

        try {
            // 验证Token和权限
            Claims claims = JwtUtils.parseJWT(token);
            String username = JwtUtils.getUserName(claims);

            // 检查Session是否有效
            if (!isSessionValid(username, sessionId)) {
                log.warn("Session ID: {} 对应的用户 '{}' 已经在其他地方登录。禁止访问: {}", sessionId, username, uri);
                sessionManager.invalidateSession(sessionId);
                assert response != null;
                response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                return null;
            }

            // 检查用户权限
            String requiredPermission = requirePermission.value();
            if (isUserAuthorized(username, requiredPermission)) {
                log.info("用户 '{}' 认证成功，权限验证通过 URI => {}", username, uri);
                return joinPoint.proceed();
            } else {
                log.warn("用户 '{}' 无权限访问: {}", username, uri);
                assert response != null;
                response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                return null;
            }

        } catch (ExpiredJwtException e) {
            log.error("Token 已过期。访问接口: {}", uri);
            assert response != null;
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return null;

        } catch (SQLSyntaxErrorException e) {  // 添加数据库异常的捕获
            log.error("数据库操作失败: {}。访问接口: {}", e.getMessage(), uri);
            assert response != null;
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);  // 返回 500 状态码
            return null;

        } catch (Exception e) {
            // 验证Token和权限
            Claims claims = JwtUtils.parseJWT(token);
            String username = JwtUtils.getUserName(claims);
            log.error("Token 验证失败: {}。用户 '{}'，访问接口: {}", e.getMessage(),username, uri);
            assert response != null;
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            return null;
        }

    }
    // 从Cookies中获取SESSIONID
    private String getSessionIdFromCookies(Cookie[] cookies) {
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if (USER_SESSION_NAME.equals(cookie.getName())) {
                    return cookie.getValue();
                }
            }
        }
        return null;
    }

    private boolean isSessionValid(String username, String sessionId) {
        Users user = usersMapper.findByUsername(username);
        if (user == null) {
            return false;
        }
        // 检查Session是否有效
        Long userId = user.getId();
        String validSessionId = sessionManager.getSessionByUserId(userId);
        return sessionId.equals(validSessionId);
    }

    private boolean isUserAuthorized(String username, String requiredPermission) {
        if (username == null || requiredPermission == null) {
            return false;
        }
        // 检查用户是否被禁用
        Users user = usersMapper.findByUsername(username);
        if (user == null || user.getStatus() == STATUS_DISABLED) {
            log.info("用户 '{}' 已被禁用或不存在", username);
            return false;
        }

        // 获取用户权限集合
        List<String> userPermissions = userRoleMapper.getUserPermissions(user.getId());
        return userPermissions.contains(requiredPermission);
    }
}

